
#ifndef XSPI_H			/* prevent circular inclusions */
#define XSPI_H			/* by using protection macros */

#ifdef __cplusplus
extern "C" {
#endif

/***************************** Include Files *********************************/

#include "xil_types.h"
#include "xil_assert.h"
#include "xstatus.h"
#include "xspi_l.h"
#include <stdio.h>
/************************** Constant Definitions *****************************/





/** @name Configuration options
 *
 * The following options may be specified or retrieved for the device and
 * enable/disable additional features of the SPI.  Each of the options
 * are bit fields, so more than one may be specified.
 *
 * @{
 */
/**
 * <pre>
 * The Master option configures the SPI device as a master. By default, the
 * device is a slave.
 *
 * The Active Low Clock option configures the device's clock polarity. Setting
 * this option means the clock is active low and the SCK signal idles high. By
 * default, the clock is active high and SCK idles low.
 *
 * The Clock Phase option configures the SPI device for one of two transfer
 * formats.  A clock phase of 0, the default, means data if valid on the first
 * SCK edge (rising or falling) after the slave select (SS) signal has been
 * asserted. A clock phase of 1 means data is valid on the second SCK edge
 * (rising or falling) after SS has been asserted.
 *
 * The Loopback option configures the SPI device for loopback mode.  Data is
 * looped back from the transmitter to the receiver.
 *
 * The Manual Slave Select option, which is default, causes the device not
 * to automatically drive the slave select.  The driver selects the device
 * at the start of a transfer and deselects it at the end of a transfer.
 * If this option is off, then the device automatically toggles the slave
 * select signal between bytes in a transfer.
 * </pre>
 */
#define XSP_MASTER_OPTION		0x1
#define XSP_CLK_ACTIVE_LOW_OPTION	0x2
#define XSP_CLK_PHASE_1_OPTION		0x4
#define XSP_LOOPBACK_OPTION		0x8
#define XSP_MANUAL_SSELECT_OPTION	0x10
/*@}*/

/**************************** Type Definitions *******************************/

/******************************************************************************/
/**
* The handler data type allows the user to define a callback function to
* handle the asynchronous processing of the SPI driver.  The application using
* this driver is expected to define a handler of this type to support interrupt
* driven mode.  The handler executes in an interrupt context such that minimal
* processing should be performed.
*
* @param CallBackRef	A callback reference passed in by the upper layer when
*			setting the callback functions, and passed back to the
*			upper layer when the callback is invoked. Its type is
*			unimportant to the driver component, so it is a void
*			pointer.
* @param StatusEvent	Indicates one or more status events that occurred. See
*			the XSpi_SetStatusHandler() for details on the status
*			events that can be passed in the callback.
* @param ByteCount	Indicates how many bytes of data were successfully
*			transferred.  This may be less than the number of bytes
*			requested if the status event indicates an error.
*
*******************************************************************************/
typedef void (*XSpi_StatusHandler) (void *CallBackRef, u32 StatusEvent,
					unsigned int ByteCount);

/**
 * XSpi statistics
 */
typedef struct {
	u32 ModeFaults;		/**< Number of mode fault errors */
	u32 XmitUnderruns;	/**< Number of transmit underruns */
	u32 RecvOverruns;	/**< Number of receive overruns */
	u32 SlaveModeFaults;	/**< Num of selects as slave while disabled */
	u32 BytesTransferred;	/**< Number of bytes transferred */
	u32 NumInterrupts;	/**< Number of transmit/receive interrupts */
} XSpi_Stats;

/**
 * This typedef contains configuration information for the device.
 */
typedef struct {
	int fd;
	u16 DeviceId;		/**< Unique ID  of device */
	UINTPTR BaseAddress;	/**< Base address of the device */
	void* Map;
	int HasFifos;		/**< Does device have FIFOs? */
	u32 SlaveOnly;		/**< Is the device slave only? */
	u8 NumSlaveBits;	/**< Num of slave select bits on the device */
	u8 DataWidth;		/**< Data transfer Width */
	u8 SpiMode;		/**< Standard/Dual/Quad mode */
	u8 AxiInterface;	/**< AXI-Lite/AXI Full Interface */
	u32 AxiFullBaseAddress;	/**< AXI Full Interface Base address of
					the device */
	u8 XipMode;             /**< 0 if Non-XIP, 1 if XIP Mode */
	u8 Use_Startup;		/**< 1 if Starup block is used in h/w */
	u16 FifosDepth;		/**< TX and RX FIFO Depth */
} XSpi_Config;

/**
 * The XSpi driver instance data. The user is required to allocate a
 * variable of this type for every SPI device in the system. A pointer
 * to a variable of this type is then passed to the driver API functions.
 */
typedef struct {
	XSpi_Stats Stats;	/**< Statistics */
	UINTPTR BaseAddr;		/**< Base address of device (IPIF) */
	int IsReady;		/**< Device is initialized and ready */
	int IsStarted;		/**< Device has been started */
	int HasFifos;		/**< Device is configured with FIFOs or not */
	u32 SlaveOnly;		/**< Device is configured to be slave only */
	u8 NumSlaveBits;	/**< Number of slave selects for this device */
	u8 DataWidth;		/**< Data Transfer Width 8 or 16 or 32 */
	u8 SpiMode;		/**< Standard/Dual/Quad mode */
	u32 SlaveSelectMask;	/**< Mask that matches the number of SS bits */
	u32 SlaveSelectReg;	/**< Slave select register */

	u8 *SendBufferPtr;	/**< Buffer to send  */
	u8 *RecvBufferPtr;	/**< Buffer to receive */
	unsigned int RequestedBytes; /**< Total bytes to transfer (state) */
	unsigned int RemainingBytes; /**< Bytes left to transfer (state) */
	int IsBusy;		/**< A transfer is in progress (state) */

	XSpi_StatusHandler StatusHandler; /**< Status Handler */
	void *StatusRef;	/**< Callback reference for status handler */
	u32 FlashBaseAddr;    	/**< Used in XIP Mode */
	u8 XipMode;             /**< 0 if Non-XIP, 1 if XIP Mode */
	u16 FifosDepth;		/**< TX and RX FIFO Depth */
} XSpi;

/***************** Macros (Inline Functions) Definitions *********************/

/******************************************************************************/
/**
*
* This macro writes to the global interrupt enable register to enable
* interrupts from the device.
*
* Interrupts enabled using XSpi_IntrEnable() will not occur until the global
* interrupt enable bit is set by using this function.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	None.
*
* @note		C-Style signature:
*		void XSpi_IntrGlobalEnable(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IntrGlobalEnable(InstancePtr)				\
	XSpi_WriteReg(((InstancePtr)->BaseAddr),  XSP_DGIER_OFFSET, 	\
			XSP_GINTR_ENABLE_MASK)

/******************************************************************************/
/**
*
* This macro disables all interrupts for the device by writing to the Global
* interrupt enable register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	None.
*
* @note		C-Style signature:
*		void XSpi_IntrGlobalDisable(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IntrGlobalDisable(InstancePtr) 				\
	XSpi_WriteReg(((InstancePtr)->BaseAddr),  XSP_DGIER_OFFSET, 0)

/*****************************************************************************/
/**
*
* This function determines if interrupts are enabled at the global level by
* reading the global interrupt register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return
*		- TRUE if global interrupts are enabled.
*		- FALSE if global interrupts are disabled.
*
* @note		C-Style signature:
*		int XSpi_IsIntrGlobalEnabled(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IsIntrGlobalEnabled(InstancePtr)				\
	(XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_DGIER_OFFSET) ==  \
		XSP_GINTR_ENABLE_MASK)

/*****************************************************************************/
/**
*
* This function gets the contents of the Interrupt Status Register.
* This register indicates the status of interrupt sources for the device.
* The status is independent of whether interrupts are enabled such
* that the status register may also be polled when interrupts are not enabled.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	A status which contains the value read from the Interrupt
*		Status Register.
*
* @note		C-Style signature:
*		u32 XSpi_IntrGetStatus(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IntrGetStatus(InstancePtr) \
	XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_IISR_OFFSET)

/*****************************************************************************/
/**
*
* This function clears the specified interrupts in the Interrupt status
* Register. The interrupt is cleared by writing to this register with the bits
* to be cleared set to a one and all others bits to zero. Setting a bit which
* is zero within this register causes an interrupt to be generated.
*
* This function writes only the specified value to the register such that
* some status bits may be set and others cleared.  It is the caller's
* responsibility to get the value of the register prior to setting the value
* to prevent an destructive behavior.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
* @param	ClearMask is the Bitmask for interrupts to be cleared.
*		Bit positions of "1" clears the interrupt. Bit positions of 0
*		will keep the previous setting. This mask is formed by OR'ing
*		XSP_INTR_* bits defined in xspi_l.h.
*
* @return	None.
*
* @note		C-Style signature:
*		void XSpi_IntrClear(XSpi *InstancePtr, u32 ClearMask);
*
******************************************************************************/
#define XSpi_IntrClear(InstancePtr, ClearMask) 			\
	XSpi_WriteReg(((InstancePtr)->BaseAddr),  XSP_IISR_OFFSET,	\
		XSpi_IntrGetStatus(InstancePtr) | (ClearMask))


/******************************************************************************/
/**
*
* This function sets the contents of the Interrupt Enable Register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
* @param	EnableMask is the bitmask of the interrupts to be enabled.
*		Bit positions of 1 will be enabled. Bit positions of 0 will
*		keep the previous setting. This mask is formed by OR'ing
*		XSP_INTR_* bits defined in xspi_l.h.
*
* @return 	None.
*
* @note		C-Style signature:
*		void XSpi_IntrEnable(XSpi *InstancePtr, u32 EnableMask);
*
******************************************************************************/
#define XSpi_IntrEnable(InstancePtr, EnableMask)			\
	XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_IIER_OFFSET,	\
		(XSpi_ReadReg(((InstancePtr)->BaseAddr), 		\
			XSP_IIER_OFFSET)) | (((EnableMask) & XSP_INTR_ALL )))

/****************************************************************************/
/**
*
* Disable the specified Interrupts in the Interrupt Enable Register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
* @param	DisableMask is the bitmask of the interrupts to be disabled.
*		Bit positions of 1 will be disabled. Bit positions of 0 will
*		keep the previous setting. This mask is formed by OR'ing
*		XSP_INTR_* bits defined in xspi_l.h.
*
* @return	None.
*
* @note		C-Style signature:
*		void XSpi_IntrDisable(XSpi *InstancePtr, u32 DisableMask);
*
******************************************************************************/
#define XSpi_IntrDisable(InstancePtr, DisableMask) 			\
	XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_IIER_OFFSET,	\
		XSpi_ReadReg(((InstancePtr)->BaseAddr), 		\
			XSP_IIER_OFFSET) & (~ ((DisableMask) & XSP_INTR_ALL )))


/*****************************************************************************/
/**
*
* This function gets the contents of the Interrupt Enable Register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	The contents read from the Interrupt Enable Register.
*
* @note		C-Style signature:
*		u32 XSpi_IntrGetEnabled(XSpi *InstancePtr)
*
******************************************************************************/
#define XSpi_IntrGetEnabled(InstancePtr) \
	XSpi_ReadReg(((InstancePtr)->BaseAddr),  XSP_IIER_OFFSET)

/****************************************************************************/
/**
*
* Set the contents of the control register. Use the XSP_CR_* constants defined
* above to create the bit-mask to be written to the register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
* @param	Mask is the 32-bit value to write to the control register.
*
* @return	None.
*
* @note		C-Style signature:
* 		void XSpi_SetControlReg(XSpi *InstancePtr, u32 Mask);
*
*****************************************************************************/
#define XSpi_SetControlReg(InstancePtr, Mask) \
	XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET, (Mask))

/****************************************************************************/
/**
*
* Get the contents of the control register. Use the XSP_CR_* constants defined
* above to interpret the bit-mask returned.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	A 32-bit value representing the contents of the control
*		register.
*
* @note		C-Style signature:
* 		u32 XSpi_GetControlReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetControlReg(InstancePtr) \
	XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET)

/***************************************************************************/
/**
*
* Get the contents of the status register. Use the XSP_SR_* constants defined
* above to interpret the bit-mask returned.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	An 32-bit value representing the contents of the status
*		register.
*
* @note		C-Style signature:
* 		u8 XSpi_GetStatusReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetStatusReg(InstancePtr) \
	XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_SR_OFFSET)

/****************************************************************************/
/**
*
* Set the contents of the XIP control register. Use the XSP_CR_XIP_* constants
* defined above to create the bit-mask to be written to the register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
* @param	Mask is the 32-bit value to write to the control register.
*
* @return	None.
*
* @note		C-Style signature:
* 		void XSpi_SetXipControlReg(XSpi *InstancePtr, u32 Mask);
*
*****************************************************************************/
#define XSpi_SetXipControlReg(InstancePtr, Mask) \
	XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET, (Mask))

/****************************************************************************/
/**
*
* Get the contents of the XIP control register. Use the XSP_CR_XIP_* constants
* defined above to interpret the bit-mask returned.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	A 32-bit value representing the contents of the control
*		register.
*
* @note		C-Style signature:
* 		u32 XSpi_GetXipControlReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetXipControlReg(InstancePtr) \
	XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET)

/****************************************************************************/
/**
*
* Get the contents of the status register. Use the XSP_SR_XIP_* constants
* defined above to interpret the bit-mask returned.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	An 32-bit value representing the contents of the status
*		register.
*
* @note		C-Style signature:
* 		u8 XSpi_GetXipStatusReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetXipStatusReg(InstancePtr) \
	XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_SR_OFFSET)

/****************************************************************************/
/**
*
* Set the contents of the slave select register. Each bit in the mask
* corresponds to a slave select line. Only one slave should be selected at
* any one time.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
* @param	Mask is the 32-bit value to write to the slave select register.
*
* @return	None.
*
* @note		C-Style signature:
* 		void XSpi_SetSlaveSelectReg(XSpi *InstancePtr, u32 Mask);
*
*****************************************************************************/
#define XSpi_SetSlaveSelectReg(InstancePtr, Mask) \
	XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_SSR_OFFSET, (Mask))

/****************************************************************************/
/**
*
* Get the contents of the slave select register. Each bit in the mask
* corresponds to a slave select line. Only one slave should be selected at
* any one time.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	The 32-bit value in the slave select register.
*
* @note		C-Style signature:
* 		u32 XSpi_GetSlaveSelectReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetSlaveSelectReg(InstancePtr) 			\
	XSpi_ReadReg((InstancePtr)->BaseAddr, XSP_SSR_OFFSET)

/****************************************************************************/
/**
*
* Enable the device and uninhibit master transactions. Preserves the current
* contents of the control register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	None.
*
* @note		C-Style signature:
* 		void XSpi_Enable(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_Enable(InstancePtr) \
{ \
	u16 Control; \
	Control = XSpi_GetControlReg((InstancePtr)); \
	Control |= XSP_CR_ENABLE_MASK; \
	Control &= ~XSP_CR_TRANS_INHIBIT_MASK; \
	XSpi_SetControlReg((InstancePtr), Control); \
}

/****************************************************************************/
/**
*
* Disable the device. Preserves the current contents of the control register.
*
* @param	InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return	None.
*
* @note		C-Style signature:
* 		void XSpi_Disable(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_Disable(InstancePtr) \
	XSpi_SetControlReg((InstancePtr), \
	XSpi_GetControlReg((InstancePtr)) & ~XSP_CR_ENABLE_MASK)

/************************** Function Prototypes ******************************/

/*
 * Initialization functions in xspi_sinit.c
 */
int XSpi_Initialize(XSpi *InstancePtr, u16 DeviceId);
XSpi_Config *XSpi_LookupConfig(u16 DeviceId);

/*
 * Functions, in xspi.c
 */
int XSpi_CfgInitialize(XSpi *InstancePtr, XSpi_Config * Config,
		       UINTPTR EffectiveAddr);

int XSpi_Start(XSpi *InstancePtr);
int XSpi_Stop(XSpi *InstancePtr);

void XSpi_Reset(XSpi *InstancePtr);

int XSpi_SetSlaveSelect(XSpi *InstancePtr, u32 SlaveMask);
u32 XSpi_GetSlaveSelect(XSpi *InstancePtr);

int XSpi_Transfer(XSpi *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr,
		  unsigned int ByteCount);

void XSpi_SetStatusHandler(XSpi *InstancePtr, void *CallBackRef,
			   XSpi_StatusHandler FuncPtr);
void XSpi_InterruptHandler(void *InstancePtr);


/*
 * Functions for selftest, in xspi_selftest.c
 */
int XSpi_SelfTest(XSpi *InstancePtr);

/*
 * Functions for statistics, in xspi_stats.c
 */
void XSpi_GetStats(XSpi *InstancePtr, XSpi_Stats *StatsPtr);
void XSpi_ClearStats(XSpi *InstancePtr);

/*
 * Functions for options, in xspi_options.c
 */
int XSpi_SetOptions(XSpi *InstancePtr, u32 Options);
u32 XSpi_GetOptions(XSpi *InstancePtr);

#ifdef __cplusplus
}
#endif

#endif /* end of protection macro */
/** @} */
